<?php
/**
 * Created by 项目.
 * User: xuguopeng
 * Date: 2019-11-08
 * Time: 15:51
 */

namespace app\api\service;

use app\api\model\GoodsOrder;
use app\api\model\GoodsOrderContent;
use app\api\model\MoneyOrder;
use app\api\model\StoreOrder;
use app\api\service\order\GoodsOrderSer;
use app\api\service\order\MoneyOrderSer;
use app\api\service\order\StoreOrderSer;
use app\lib\exception\ParameterException;
use app\lib\exception\TokenException;
use think\facade\Log;


class Pay extends Token
{
    // 支付number
    private $outTradeNo;

    // 订单金额
    private $price;

    // 订单类型
    private $type;

    // 用户ID
    private $uid;

    // 订单
    private $order;

    function __construct($outTradeNo)
    {
        $this->outTradeNo = $outTradeNo;
    }

    /**
     * 根据支付number获取订单类型
     * 判断订单信息
     * 生成预支付ID
     * 返回 信息
     */
    public function pay()
    {
        return $this->getType();
    }

    // 生成类型
    private function getType()
    {
        $this->uid = self::getCurrentUid();
        $outTradeNo = explode("z",$this->outTradeNo);
        $this->type = $outTradeNo[0];
        return $this->checkOrder();
    }

    // 判断订单信息
    private function checkOrder()
    {
        if($this->type == 1) {
            $this->order = MoneyOrder::where('out_trade_no',$this->outTradeNo)->find();
            $this->price = $this->order['price'];
        } elseif($this->type == 2) {
            $this->order = StoreOrder::where('out_trade_no',$this->outTradeNo)->find();
            $this->price = round($this->order['price'] - $this->order['coupon_price'],2);
        }  elseif($this->type == 3) {
            $this->order = GoodsOrder::where('out_trade_no',$this->outTradeNo)->find();
            $this->price = round($this->order['price'] - $this->order['coupon_price'],2);
            $this->judgeOrderContentNumber();
        }
        $this->checkOrderPublic();
        return $this->makeWxPreOrder();
    }


    // 判断商品库存
    private function judgeOrderContentNumber()
    {
        $orderContent = GoodsOrderContent::with('goods')->where('order_id',$this->order['id'])->select()->toArray();
        if(count($orderContent) == 0) {
            throw new ParameterException([
                'msg' => [
                    'goods' => '订单为空'
                ]
            ]);
        }
        foreach ($orderContent as $k=>$v) {
              if($orderContent[$k]['number'] > $orderContent[$k]['goods']['number']) {
                 throw new ParameterException([
                     'msg' => [
                        'goods' => $orderContent[$k]['goods']['name'].' 库存不足'
                     ]
                 ]);
             }
             if($orderContent[$k]['goods']['up_down'] == 2) {
                 throw new ParameterException([
                     'msg' => [
                         'goods' => $orderContent[$k]['goods']['name'].' 已下架'
                     ]
                 ]);
             }
        }
    }

    // 判断会员订单
    private function checkOrderPublic()
    {
        // 订单是否存在
        if(!$this->order) {
            throw new ParameterException([
                'msg' => [
                    'order' => '订单不存在,请重新选择订单'
                ]
            ]);
        }
        if($this->type == 2) {
            // 订单状态
            if($this->order['status'] != 3) {
                throw new ParameterException([
                    'msg' => [
                        'order' => '订单已经支付'
                    ]
                ]);
            }
        } else {
            // 订单状态
            if($this->order['status'] != 1) {
                throw new ParameterException([
                    'msg' => [
                        'order' => '订单已经支付'
                    ]
                ]);
            }
        }
        // 订单用户
        if($this->order['user_id'] != $this->uid) {
            throw new ParameterException([
                'msg' => [
                    'order' => '订单用户与此用户不一致!'
                ]
            ]);
        }
    }

    // 生成支付订单
    private function makeWxPreOrder()
    {
        if($this->price == 0) {
            $this->changeOrder();
            return [
                'pay_type' => 2
            ];
        }
        // openid
        $openid = Token::getCurrentTokenVar('openid');
        if(!$openid)
        {
            throw new TokenException();
        }
        $wxOrderData = new \WxPayUnifiedOrder();
        $wxOrderData->SetOut_trade_no($this->outTradeNo);
        $wxOrderData->SetTrade_type('JSAPI');
        $wxOrderData->SetTotal_fee((int)($this->price*100));
        if($this->type == 1) {
            $wxOrderData->SetBody('正章掌上洗衣余额充值');
        }elseif($this->type == 2) {
            $wxOrderData->SetBody('正章掌上洗衣订单');
        }elseif($this->type == 3) {
            $wxOrderData->SetBody('正章掌上商城订单');
        }
        $wxOrderData->SetOpenid($openid);
        $wxOrderData->SetNotify_url(config('secure.pay_back_url'));
        return $this->getPaySignature($wxOrderData);
    }


    private function getPaySignature($wxOrderData)
    {
        $config = new \WxPayConfig();
        $wxOrder = \WxPayApi::unifiedOrder($config,$wxOrderData);
        if($wxOrder['return_code'] != 'SUCCESS' ||
            $wxOrder['result_code'] != 'SUCCESS')
        {
            Log::record($wxOrder,'error');
            Log::record('获取预支付订单失败','error');
            throw new ParameterException([
                'msg'=>[
                    'pay' => $wxOrder['return_msg']
                ]
            ]);
        }
        $this->recordPreOrder($wxOrder);
        return $this->sign($wxOrder);
    }

    private function sign($wxOrder)
    {
        $jsApiData = new \WxPayJsApiPay();
        $jsApiData->SetAppid(config('wx.app_id'));
        $jsApiData->SetTimeStamp((string)time());
        $rand = md5(time() .mt_rand(0,1000));
        $jsApiData->SetNonceStr($rand);
        $jsApiData->SetPackage('prepay_id='.$wxOrder['prepay_id']);
        $jsApiData->SetSignType('md5');
        $config = new \WxPayConfig();
        $sign = $jsApiData->MakeSign($config);
        $rawValues = $jsApiData->GetValues();
        $rawValues['paySign'] = $sign;
        unset($rawValues['appId']);
        $rawValues['pay_type'] = 1;
        return $rawValues;
    }

    // 更新预支付ID
    private function recordPreOrder($wxOrder)
    {
        if($this->type == 1) {
           MoneyOrder::where('out_trade_no',$this->outTradeNo)->update([
               'prepay_id' => $wxOrder['prepay_id'],
               'pay_overdue_time' => time() + 7100,
           ]);
        } elseif ($this->type == 2) {
            StoreOrder::where('out_trade_no',$this->outTradeNo)->update([
                'prepay_id' => $wxOrder['prepay_id'],
                'pay_overdue_time' => time() + 7100,
                'payment' => 1
            ]);
        }  elseif ($this->type == 3) {
            GoodsOrder::where('out_trade_no',$this->outTradeNo)->update([
                'prepay_id' => $wxOrder['prepay_id'],
                'pay_overdue_time' => time() + 7100,
                'payment' => 1
            ]);
        }
    }

    // 更新订单
    private function changeOrder()
    {
        if($this->type == 1) {
            $moneySer = new MoneyOrderSer($this->order);
            $moneySer->changeStatus();
        } elseif($this->type == 2){
            $storeOrder = new StoreOrderSer($this->order);
            $storeOrder->changeStatus();
        }  elseif($this->type == 3){
            $GoodsOrder = new GoodsOrderSer($this->order);
            $GoodsOrder->changeStatus();
        }
    }
}